package dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import model.Produto;
import database.Conexao;
import database.FabricaConexao;
import exceptions.AcessoAoBancoException;
import exceptions.ConexaoComBancoException;

public class ProdutoDao implements IProdutoDao {

	private Conexao conexao;

	private PreparedStatement statement = null;

	private ResultSet rs = null;

	private final String SQL_INSERT = "INSERT INTO Produto(nome) VALUES(?)";

	private final String SQL_DELETE = "DELETE FROM Produto WHERE cod = ?";

	private final String SQL_UPDATE = "UPDATE Produto SET nome = ? WHERE cod = ?";

	private final String SQL_SELECT = "SELECT cod, nome FROM Produto WHERE cod = ? OR nome = ?";

	private final String SQL_SELECT_CODIGO = "SELECT cod, nome FROM Produto WHERE cod = ?";

	private final String SQL_SELECT_TODOS = "SELECT cod, nome FROM Produto";

	private final String SQL_SELECT_ULTIMO = "SELECT cod FROM Produto WHERE cod = (SELECT MAX(cod) FROM Produto)";

	public ProdutoDao() {
		this.conexao = FabricaConexao.criarConexao();
	}

	public ProdutoDao(Conexao conexao) {
		this.conexao = conexao;
	}

	public void atualizar(Produto atualizado) throws ConexaoComBancoException,
			AcessoAoBancoException {
		PreparedStatement update = null;
		try {
			this.conexao.abrirConexao();
			this.statement = this.conexao.getConexao().prepareStatement(
					this.SQL_SELECT_CODIGO);
			this.statement.setInt(1, atualizado.getCod());
			this.rs = statement.executeQuery();

			if (rs.next()) {
				update = this.conexao.getConexao().prepareStatement(
						this.SQL_UPDATE);

				update.setInt(1, atualizado.getCod());
				update.setString(2, atualizado.getNome());

				update.execute();
				update.close();
			}
		} catch (SQLException e) {
			AcessoAoBancoException e1 = new AcessoAoBancoException();
			throw e1;
		} catch (ClassNotFoundException e) {
			ConexaoComBancoException e1 = new ConexaoComBancoException();
			throw e1;
		} finally {
			try {
				if (this.conexao != null)
					this.conexao.fecharConexao();

				if (this.statement != null)
					this.statement.close();

				if (this.rs != null)
					this.rs.close();

				if (update != null)
					update.close();
			} catch (SQLException e) {
				AcessoAoBancoException e1 = new AcessoAoBancoException();
				throw e1;
			}
		}

	}

	public int gerarCodigo() throws ConexaoComBancoException,
			AcessoAoBancoException {
		int proximoCodigo = 1;
		try {
			this.conexao.abrirConexao();
			this.statement = this.conexao.getConexao().prepareStatement(
					this.SQL_SELECT_ULTIMO);

			this.rs = statement.executeQuery();

			if (this.rs.next())
				proximoCodigo = rs.getInt("cod") + 1;

		} catch (SQLException e) {
			AcessoAoBancoException e1 = new AcessoAoBancoException();
			throw e1;
		} catch (ClassNotFoundException e) {
			ConexaoComBancoException e1 = new ConexaoComBancoException();
			throw e1;
		} finally {
			try {
				if (this.conexao != null)
					this.conexao.fecharConexao();

				if (this.statement != null)
					this.statement.close();

				if (this.rs != null)
					this.rs.close();
			} catch (SQLException e) {
				AcessoAoBancoException e1 = new AcessoAoBancoException();
				throw e1;
			}
		}
		return proximoCodigo;
	}

	public void inserir(Produto novoProduto) throws ConexaoComBancoException,
			AcessoAoBancoException {
		try {
			this.conexao.abrirConexao();

			this.statement = this.conexao.getConexao().prepareStatement(
					this.SQL_INSERT);
			this.statement.setString(1, novoProduto.getNome());

			this.statement.execute();
		} catch (SQLException e) {
			AcessoAoBancoException e1 = new AcessoAoBancoException();
			throw e1;
		} catch (ClassNotFoundException e) {
			ConexaoComBancoException e1 = new ConexaoComBancoException();
			throw e1;
		} finally {
			try {
				if (this.conexao != null)
					this.conexao.fecharConexao();
				if (this.statement != null)
					this.statement.close();
			} catch (SQLException e) {
				AcessoAoBancoException e1 = new AcessoAoBancoException();
				throw e1;
			}
		}

	}

	public List<Produto> listar() throws ConexaoComBancoException,
			AcessoAoBancoException {
		List<Produto> listaDeProdutos = new ArrayList<Produto>();
		try {
			this.conexao.abrirConexao();
			this.statement = this.conexao.getConexao().prepareStatement(
					this.SQL_SELECT_TODOS);
			this.rs = this.statement.executeQuery();

			while (rs.next()) {
				int codigo = this.rs.getInt(1);
				String nome = this.rs.getString(2);

				listaDeProdutos.add(new Produto(codigo, nome));
			}

		} catch (SQLException e) {
			AcessoAoBancoException e1 = new AcessoAoBancoException();
			throw e1;
		} catch (ClassNotFoundException e) {
			ConexaoComBancoException e1 = new ConexaoComBancoException();
			throw e1;
		} finally {
			try {
				if (this.conexao != null)
					this.conexao.fecharConexao();

				if (this.statement != null)
					this.statement.close();

				if (this.rs != null)
					this.rs.close();
			} catch (SQLException e) {
				AcessoAoBancoException e1 = new AcessoAoBancoException();
				throw e1;
			}
		}
		return listaDeProdutos;

	}

	public Produto localizar(int _cod, String _nome)
			throws ConexaoComBancoException, AcessoAoBancoException {
		Produto localizado = null;
		try {
			this.conexao.abrirConexao();
			this.statement = this.conexao.getConexao().prepareStatement(
					this.SQL_SELECT);
			this.statement.setInt(1, _cod);
			this.statement.setString(2, _nome);
			this.rs = this.statement.executeQuery();

			if (rs.next()) {
				int cod = this.rs.getInt(1);
				String nome = this.rs.getString(2);
				localizado = new Produto(cod, nome);
			}

		} catch (SQLException e) {
			AcessoAoBancoException e1 = new AcessoAoBancoException();
			throw e1;
		} catch (ClassNotFoundException e) {
			ConexaoComBancoException e1 = new ConexaoComBancoException();
			throw e1;
		} finally {
			try {
				if (this.conexao != null)
					this.conexao.fecharConexao();

				if (this.statement != null)
					this.statement.close();

				if (this.rs != null)
					this.rs.close();
			} catch (SQLException e) {
				AcessoAoBancoException e1 = new AcessoAoBancoException();
				throw e1;
			}
		}
		return localizado;

	}

	public void remover(int cod) throws ConexaoComBancoException,
			AcessoAoBancoException {
		try {
			this.conexao.abrirConexao();

			this.statement = this.conexao.getConexao().prepareStatement(
					this.SQL_DELETE);
			this.statement.setInt(1, cod);
			this.statement.execute();

		} catch (SQLException e) {
			AcessoAoBancoException e1 = new AcessoAoBancoException();
			throw e1;
		} catch (ClassNotFoundException e) {
			ConexaoComBancoException e1 = new ConexaoComBancoException();
			throw e1;
		} finally {
			try {
				if (this.conexao != null)
					this.conexao.fecharConexao();
				if (this.statement != null)
					this.statement.close();
			} catch (SQLException e) {
				AcessoAoBancoException e1 = new AcessoAoBancoException();
				throw e1;
			}
		}

	}

}
